/*
 * Copyright (c) 2016 JUI All rights reserved.
 */


;(function () {

    /**
     * 表格控件<br>
     * <pre>
     grid = new JUI.Grid({
		renderId:'grid'
		,autoRender:true
		,url : listUrl
		,striped:true // 斑马线
		,idField:'orderId'
		,pagination :true
		,singleSelect :false // 是否单选
		,checkOnSelect :true
		,rownumbers :true
		,selectCache :true
		,queryParams:{name:'11',age:22}
		,onLoadError:function() {
			console.log('加载失败,尝试加载本地数据')
			loadData(); // 加载失败尝试加载本地数据
		}
		,onLoadSuccess:function(e) {
			console.log(e.data)
		}
		,onBeforeLoad:function(e) {
			console.log(e.data)
		}
		,onClickRow:function(e) {
			console.log('onClickRow,' + e.index + ' mobile:' + e.row.mobile)
		}
		,onDblClickRow :function(e) {
			console.log('onDblClickRow,' + e.index + ' mobile:' + e.row.mobile)
		}
		,onClickCell :function(e) {
			console.log('onClickCell,' + e.index + ' value:' + e.value + ' field:' + e.head.field)
		}
		,onDblClickCell :function(e) {
			console.log('onDblClickCell,' + e.index + ' value:' + e.value + ' field:' + e.head.field)
		}
		,onSortColumn :function(sortName,sortOrder) {
			console.log('onSortColumn sortName:' + sortName + ',sortOrder:'+sortOrder)
		}
		,onSelect :function(e) {
			console.log('onSelect index:' + e.index + ' mobile:' + e.row.mobile)
		}
		,onUnSelect :function(e) {
			console.log('onUnSelect index:' + e.index + ' city:' + e.row.cityName)
		}
		,onSelectAll :function(e) {
			console.log('onSelectAll rows.length=' + e.rows.length)
		}
		,onUnSelectAll :function(e) {
			console.log('onUnSelectAll rows.length=' + e.rows.length)
		}
		,onCheck :function(e) {
			console.log('onCheck index:' + e.index + ' mobile:' + e.row.mobile)
		}
		,onUncheck :function(e) {
			console.log('onUncheck index:' + e.index + ' mobile:' + e.row.mobile)
		}
		,onCheckAll :function(e) {
			console.log('onCheckAll rows.length=' + e.rows.length)
		}
		,onUnCheckAll :function(e) {
			console.log('onUncheckAll rows.length=' + e.rows.length)
		}
		,columns : [ [
			{
				checkbox : true
			},
			{
				field : 'cityName',
				title : '城市'
				,halign:'left'
				,styler: function(value,row,index){
					if (value == 12){
						return 'background-color:#ffee00;color:red;';
					}
				}

			},
			{
				field : 'mobile',
				title : '手机号'
				,align:'center'
				,formatter:function(val,obj,index,$td){
					if(val == 22) {
						$td.css({'background-color':'#ccc','color':'red'});
						return '<i>'+val+'</i>'
					}
					return val;
				}
			},
			{
				field : 'address',
				title : '地址'
			},
			{
				field : 'createDate',
				title : '创建时间'
				,sortable:true
			}] 
		]
	});
     * </pre>
     * @class JUI.Grid
     * @extends JUI.Component
     */
    JUI.Class('Grid', {
        OPTS: $.extend({
            /**
             * @cfg {String} url 请求URL
             */
            url: null
            /**
             * @cfg {String} method 请求方式
             */
            , method: 'GET'
            /**
             * @cfg {String} idField 指明哪一个字段是标识字段。
             */
            , idField: null
            /**
             * @cfg {Object|Array} data 本地数据
             */
            , data: null
            /**
             * @cfg {String} width 表格宽度,'100%','auto'
             */
            , width: '100%'
            /**
             * @cfg {Array} pageList 在设置分页属性的时候 初始化页面大小选择列表。
             */
            , pageList: [10, 20, 30, 40, 50]
            /**
             * @cfg {Function} loadFilter 返回过滤数据显示。该函数带一个参数'data'用来指向源数据（即：获取的数据源，比如Json对象）。您可以改变源数据的标准数据格式。这个函数必须返回包含'total'和'rows'属性的标准数据对象。<br>
             * <pre>
             * 代码示例：

             // 从Web Service（asp.net、java、php等）输出的JSON对象中移除'd'对象
             new JUI.Grid({
	loadFilter: function(data){
		if (data.d){
			return data.d;
		} else {
			return data;
		}
	}
});
             * </pre>
             */
            , loadFilter: null
            /**
             * @cfg {Number} pageNumber 在设置分页属性的时候初始化页码。
             */
            , pageNumber: 1
            /**
             * @cfg {Number} pageSize 在设置分页属性的时候初始化页面大小。
             */
            , pageSize: 10
            /**
             * @cfg {Boolean} striped 是否显示斑马线效果。
             */
            , striped: true
            /**
             * @cfg {Boolean} hover 鼠标悬停高亮
             */
            , hover: true
            /**
             * @cfg {Boolean} bordered 为true,表格和其中的每个单元格增加边框。
             */
            , bordered: true
            /**
             * @cfg {Number} checkTdWidth checkbox列宽
             */
            , checkTdWidth: 50
            /**
             * @cfg {Boolean} checkboxDeepTrigger 全选框是否触发下面各个checkbox事件,为true则触发
             */
            , checkboxDeepTrigger: false
            /**
             * @cfg {Boolean} pagination 如果为true，则在数据表格控件底部显示分页工具栏。
             */
            , pagination: false
            /**
             * @cfg {Boolean} rownumbers 如果为true，则显示一个行号列。
             */
            , rownumbers: false
            /**
             * @cfg {Number} rownumberTitle 索引列title
             */
            , rownumberTitle: '序号'
            /**
             * @cfg {Number} rownumberTdWidth 索引列宽度
             */
            , rowNumberTdWidth: 50
            /**
             * @cfg {String}
             */
            , sortName: null
            /**
             * @cfg {String} sortOrder 定义列的排序顺序，只能是'asc'或'desc'。
             */
            , sortOrder: 'ASC'
            /**
             * @cfg {String} emptyDataMsg 没有数据时显示的提示
             */
            , emptyDataMsg: '<div style="text-align:center;">无数据</div>'
            /**
             * @cfg {String} pageSelectStyle 分页select控件样式
             */
            , pageSelectStyle: 'float:left;margin-right:10px;height:34px;border: 1px solid #ddd;'
            /**
             * @cfg {Boolean} singleSelect 如果为true，则只允许选择一行。
             */
            , singleSelect: false
            /**
             * @cfg {Boolean}
             */
            , checkOnSelect: true
            /**
             * @cfg {Object} queryParams 在请求远程数据的时候发送额外的参数。 <br>
             <pre>
             代码示例：

             $('#dg').datagrid({
	queryParams: {
		name: 'easyui',
		subject: 'datagrid'
	}
});
             </pre>
             */
            , queryParams: {}
            /**
             * @cfg {Boolean} selectCache 缓存勾选,true的话,表格翻页会记住之前的勾选状态
             */
            , selectCache: false
            /**
             * @cfg {Boolean} initLoad 初始化完成后立即加载数据
             */
            , initLoad: true
            /**
             * @cfg {Boolean} clickHighlight 点击行高亮
             */
            , clickHighlight: true
            /**
             * @cfg {Boolean} autoFit 自适应宽度,即单元格的宽度根据内容而定
             */
            , autoFit: false
            /**
             * 自定义请求,function(config,successFun,errorFun){}<br>
             * <pre>
             * config内容：
             * {
                    url: url // url
                    , method: this.opt('method') // 请求方式get,post
                    , data: schData // 查询参数
                    , dataType: 'json'
                }
             * </pre>
             * @cfg {Function} loader 
             */
            , loader: null
            /**
             * @cfg {String} requestPageIndexName 发送请求的页索引属性名,默认'page'
             */

            /**
             * @cfg {String} requestPageSizeName 发送请求的每页大小属性名,默认'rows'
             */

            /**
             * @cfg {String} requestSortName 发送请求的排序字段属性名,默认'sort'
             */

            /**
             * @cfg {String} requestOrderName 发送请求的排序规则属性名,默认'order'
             */

            /**
             * @cfg {String} serverPageSizeName 服务器端返回json数据的页大小标识,默认'pageSize'
             */

            /**
             * @cfg {String} serverTotalName 服务器端返回json数据的总记录数标识,默认'total'
             */

            /**
             * @cfg {String} serverRowsName 服务器端返回json数据的rows标识,默认'rows'
             */

            /**
             * @cfg {String} tableCss 表格默认样式className,默认'table'
             */

            /**
             * @cfg {String} tableStripedCss 斑马线样式,默认'table-striped'
             */

            /**
             * @cfg {String} tableHoverCss 鼠标悬停高亮样式,默认'table-hover'
             */

            /**
             * @cfg {String} tableBrderedCss 表格边框样式,默认'table-bordered'
             */

        }, JUIConfig.Grid)

        // ----- 事件注释 -----

        /** 
         * @event onLoadSuccess 在数据加载成功的时候触发。
         * @param {Object} e e.data 返回对象
         * */

        /**
         * @event onRefreshSuccess 在载入远程数据产生错误的时候触发。
         * @param {Object} e e.$table table的jquery对象,e.grid grid对象,e.data 数据
         */

        /**
         * @event onLoadError 在载入远程数据产生错误的时候触发。
         * @param {Object} e e.xhr XMLHttpRequest对象,e.status 响应状态,e.error 错误信息
         */

        /**
         * @event onBeforeLoad 在载入请求数据数据之前触发，如果返回false可终止载入数据操作。
         * @param {Object} e e.data 查询参数
         */

        /**
         * @event onClickRow 在用户点击一行的时候触发
         * @param {Object} e e.index 行索引,e.row 行记录,e.target 点击的dom
         */

        /**
         * @event onDblClickRow 在用户双击一行的时候触发
         * @param {Object} e e.index 行索引,e.row 行记录,e.target 点击的dom
         */

        /**
         * @event onClickCell 在用户点击一个单元格的时候触发。
         * @param {Object} e e.value 单元格的值,e.head 表头配置对象,e.index 行索引,e.row 行记录,e.target 点击的dom
         */

        /**
         * @event onDblClickCell 在用户双击一个单元格的时候触发
         * @param {Object} e e.value 单元格的值,e.head 表头配置对象,e.index 行索引,e.row 行记录,e.target 点击的dom
         */

        /**
         * @event onSortColumn 在用户点击排序时触发
         * @param {String} sortName 排序字段名
         * @param {String} sortOrder 排序方式,ASC DESC
         */

        /**
         * @event onSelect 在用户选择一行时触发,单选情况下
         * @param {Object} e e.index 行索引,e.row 行记录,e.$target input对象
         */

        /**
         * @event onUnSelect 在用户取消选择一行时触发,单选情况下
         * @param {Object} e e.index 行索引,e.row 行记录,e.$target input对象
         */

        /**
         * @event onCheck 在用户勾选一行的时候触发
         * @param {Object} e e.index 行索引,e.row 行记录,e.$target input对象
         */

        /**
         * @event onUncheck 在用户取消勾选一行的时候触发
         * @param {Object} e e.index 行索引,e.row 行记录,e.$target input对象
         */

        /**
         * @event onCheckAll 在用户勾选所有行的时候触发
         * @param {Object} e e.rows 选中的数据
         */

        /**
         * @event onUnCheckAll 在用户取消勾选所有行的时候触发
         * @param {Object} e e.rows 选中的数据
         */


        /**
         * 构造函数
         * @ignore
         */
        , init: function (opts) {
            this._super(opts);
        }
        // @override
        , afterRender: function () {
            this.page = new JUI.Page(this);
            if (this.opt('initLoad')) {
                this.load();
            }
        }
        /**
         * 清空勾选缓存
         */
        , resetSelectCache: function () {
            this.selectCache = {};
        }
        /**
         * @private
         */
        , getSelectCache: function () {
            if (!this.selectCache) {
                this.selectCache = {};
            }
            return this.selectCache;
        }
        /**
         * @private
         */
        , isSelectCache: function () {
            return this.opt('selectCache');
        }
        /**
         * @private
         */
        , isInCache: function (value) {
            if (!value) {
                return false;
            }
            return !!this.selectCache[value];
        }
        , hasData: function () {
            var hasData = this.data
                && this.data[this.opt('serverRowsName')]
                && this.data[this.opt('serverRowsName')].length > 0;
            return hasData;
        }
        /**
         * 加载数据
         * @param {Object} schData 查询参数,JSON数据
         */
        , load: function (schData) {
            this.resetSelectCache();
            if (this.opt('url')) {
                this.schData = schData || {};
                this.schData = $.extend(this.schData, this.opt('queryParams'));
                this.goPage(1);
            } else {
                var data = this.opt('data');
                this.loadData(data);
            }

        }
        /**
         * 跳转到第几页
         * @param {Number} pageIndex 跳转到第几页
         */
        , goPage: function (pageIndex) {
            pageIndex = parseInt(pageIndex) || 1;
            this.page.goPage(pageIndex);
        }
        /**
         * 重载行。等同于'load'方法，但是它将保持在当前页。
         */
        , reload: function () {
        	var that = this;
            var schData = this.buildSchData();
            var ret = this.fire('BeforeLoad', {data: schData});

            if (ret === false) {
                return;
            }

            var url = this.opt('url');
            var loader = this.opt('loader');
            
            var httpConfig = {
                    url: url
                    , method: this.opt('method')
                    , data: schData
                    , dataType: 'json'
                }
            
            if(loader) {
            	loader(httpConfig, function(resp) {
        			that.bindResult(resp);
        		});
            } else if (url) {
                this.requestServer(httpConfig);
            } else {
                this.requestLocal(this.page.pageIndex, this.page.pageSize);
            }
        }
        /**
         * @private
         */
        , requestServer: function (config) {
        	var that = this;
        	$.ajax({
    			type: config.method,
    			url: config.url,
    			traditional: true,
    			dataType: config.dataType,
    			data: config.data,
    			success: function (data, textStatus, jqXHR) {
    				that.bindResult(data);
    			},
    			error: function (XMLHttpRequest, textStatus, errorThrown) {
    				that.fire('LoadError', {xhr: XMLHttpRequest, status: textStatus, error: errorThrown});
    			}
    		});
        }
        /**
         * @private
         */
        , requestLocal: function (pageIndex, pageSize) {
            var that = this;
            var newData = [];
            var rows = this.localData[this.opt('serverRowsName')];
            var firstIndex = 1, total = 0;

            if (that.opt('pagination') && rows.length > 0) {
                firstIndex = parseInt((pageIndex - 1) * pageSize);
                total = rows.length;
                newData = rows.slice(firstIndex, firstIndex + pageSize);
            } else {
                newData = rows;
            }
            var obj = {};

            obj[that.opt('serverRowsName')] = newData;
            obj[that.opt('serverPageIndexName')] = pageIndex;
            obj[that.opt('serverPageSizeName')] = pageSize;
            obj[that.opt('serverTotalName')] = total;

            that.bindResult(obj);
        }
        /**
         * 移除表格内容
         */
        , removeData: function () {
            this.bindResult({});
        }
        /**
         * 加载本地数据，旧的行将被移除。
         * @param {Object} data 本地数据
         */
        , loadData: function (data) {
            data = data || {};
            this.opt('url', '');
            this.resetSelectCache();

            this.localData = this.formatData(data);

            this.goPage(1);
        }
        /**
         * @private
         */
        , bindResult: function (data) {
            data = this.formatData(data);

            this.fire('LoadSuccess', {data: data});

            this.data = this.filterData(data);

            this.page.setPageInfo(this.data);

            this.view.refresh();
        }
        /**
         * 设置每页大小
         * @param {Number} size
         */
        , setPageSize: function (size) {
            size = parseInt(size) || this.opt('pageSize');
            this.page.setPageSize(size);
        }
        /**
         * 获取请求数据
         * @return {JSON} 请求数据
         */
        , getData: function () {
            return this.data;
        }
        /**
         * 获取行数据
         * @return {Array} 返回数组
         */
        , getRows: function () {
            return this.data[this.opt('serverRowsName')];
        }
        /**
         * 返回勾选的行数据
         * @return {Array}
         */
        , getChecked: function () {
            var checkedDatas = [];

            // 先添加缓存中的
            if (this.isSelectCache()) {
                var selectCache = this.getSelectCache();
                for (var idVal in selectCache) {
                    if (selectCache[idVal]) {
                        checkedDatas.push(selectCache[idVal]);
                    }
                }
            }

            var checkedIndexs = this.view.getCheckedIndex();

            for (var i = 0, len = checkedIndexs.length; i < len; i++) {
                var index = checkedIndexs[i];
                var row = this.getRowByIndex(index);
                var value = row[this.opt('idField')];

                var isNotInCache = !this.isInCache(value);
                if (isNotInCache) {
                    checkedDatas.push(row);
                }
            }
            return checkedDatas;
        }
        /**
         * 返回勾选的行数据的主键集合,getChecked()则是返回整个对象
         * @return {Array} 如:[1,2,4]
         */
        , getCheckIds: function () {
            var checkedRows = this.getChecked();
            var ret = [];
            var idField = this.opt('idField');

            for (var i = 0, len = checkedRows.length; i < len; i++) {
                var row = checkedRows[i];
                ret.push(row[idField]);
            }

            return ret;
        }
        /**
         * 返回第一个被选中的行或如果没有选中的行则返回null。
         */
        , getSelected: function () {
            var checkedDatas = this.getChecked();
            if (checkedDatas.length == 0) {
                return null;
            }
            return checkedDatas[0];
        }
        /**
         * 根据索引返回数据
         */
        , getRowByIndex: function (index) {
            var rows = this.getRows();
            return rows[index];
        }
        /**
         * 勾选全部
         */
        , checkAll: function () {
            this.view.checkAll();
        }
        /**
         * 不勾选全部
         */
        , uncheckAll: function () {
            this.view.uncheckAll();
        }
        /**
         * 不勾选全部
         */
        , clearChecked: function () {
            this.uncheckAll();
        }
        /**
         * 不勾选全部
         */
        , unselectAll: function () {
            this.uncheckAll();
        }
        /**
         * 不勾选全部
         */
        , clearSelections: function () {
            this.uncheckAll();
        }
        /**
         * 根据索引选择行
         * @param {Number} index 行索引
         */
        , selectRow: function (index) {
            this.view.selectRow(index);
        }
        /**
         * 根据索引不选择行
         * @param {Number} index 行索引
         */
        , unselectRow: function (index) {
            this.view.unselectRow(index);
        }
        /**
         * 根据索引勾选行
         * @param {Number} index 行索引
         */
        , checkRow: function (index) {
            this.view.checkRow(index);
        }
        /**
         * 根据索不引勾选行
         * @param {Number} index 行索引
         */
        , uncheckRow: function (index) {
            this.view.uncheckRow(index);
        }
        /**
         * 通过ID值参数选择一行。
         */
        , selectRecord: function (idVal) {
            this.view.selectRecord(idVal);
        }
        /**
         * @private
         */
        , isCheckedAll: function () {
            return this.view.isCheckedAll();
        }
        /**
         * 排序,只支持单属性排序
         * @param {String} sortName 排序字段名
         * @param {String} sortOrder 排序方式,即ASC,DESC
         */
        , sort: function (sortName, sortOrder) {
            this.opt('sortName', sortName);
            this.opt('sortOrder', sortOrder);

            this.fire('SortColumn', {sortName: sortName, sortOrder: sortOrder});

            this.goPage(1);
        }
        /**
         * @ignore
         */
        , getViewClass: function () {
            return JUI.GridView;
        }
        /**
         * @private
         */
        , buildSchData: function () {
            var param = this.schData || {};
            var pageData = this.page.getPageData();

            param = $.extend(param, pageData);

            // 排序字段
            if (this.opt('sortName')) {
                param[this.opt('requestSortName')] = this.opt('sortName');
                param[this.opt('requestOrderName')] = this.opt('sortOrder');
            }

            return param;
        }
        , getTableWidth: function () {
            var width = this.opt('width');

            if (this.opt('autoFit')) {
                width = 'auto';
            }

            return width;
        }
        /**
         * @private
         */
        , formatData: function (data) {
            data = data || {};
            if ($.isArray(data)) {
                var obj = {};
                obj[this.opt('serverRowsName')] = data;
                data = obj;
            }
            if (!data[this.opt('serverRowsName')]) {
                data[this.opt('serverRowsName')] = [];
            }
            return data;
        }
        /**
         * @private
         */
        , filterData: function (data) {
            var loadFilter = this.opt('loadFilter');
            if ($.isFunction(loadFilter)) {
                data = loadFilter(data);
            }
            return data;
        }

    }, JUI.Component);


})();